﻿using Md.Api.DDD;
using Md.Api.Model.Util.Upload.Request;
using Md.Api.Model.Util.Upload.Response;
using Microsoft.AspNetCore.Http;

namespace Md.Util.Service.Upload;
/// <summary>
/// 文件分片上传服务
/// </summary>
public class MultipartUploadService : ApiBase<RequestMultipartUploadModel>
{
    /// <summary>
    /// 执行
    /// </summary>
    protected override void ExecuteMethod()
    {
        if (Parameter.Form == null || Parameter.Form.Files == null || Parameter.Form.Files.Count == 0)
        {
            throw new AggregateException("请选择文件");
        }

        Parameter.Index = Convert.ToInt64(Parameter.Form["index"]);
        Parameter.Name = Parameter.Form["name"];
        Parameter.Size = Convert.ToInt64(Parameter.Form["size"]);
        Parameter.Ext = Parameter.Form["ext"];
        Parameter.FileMD5 = Parameter.Form["fileMD5"];
        Parameter.ChunkName = Parameter.Form["chunkName"];
        Parameter.ChunkMD5 = Parameter.Form["chunkMD5"];
        Parameter.ChunkSize = Convert.ToInt64(Parameter.Form["chunkSize"]);
        Parameter.ChunkCount = Convert.ToInt64(Parameter.Form["chunkCount"]);
        Parameter.UId = Parameter.Form["uid"];
        Parameter.ChunkStart = Convert.ToInt64(Parameter.Form["chunkStart"]);
        Parameter.ChunkEnd = Convert.ToInt64(Parameter.Form["chunkEnd"]);

        var tempFileFolder = Path.Combine(FileBasePath, $"{Parameter.UId}");

        if (!Directory.Exists(tempFileFolder))
        {
            Directory.CreateDirectory(tempFileFolder);
        }

        IFormFile? file = Parameter.Form.Files[0];

        var stream = file.OpenReadStream();
        byte[] bytes = new byte[stream.Length];
        stream.Read(bytes, 0, bytes.Length);

        var tempFileName = Path.Combine(tempFileFolder, $"{Parameter.ChunkName}.temp");

        var fileStream = new FileStream(tempFileName, FileMode.Create);

        file.CopyTo(fileStream);

        fileStream.Flush();
        fileStream.Close();
        fileStream.Dispose();

        // 文件合并
        if (Parameter.Index + 1 == Parameter.ChunkCount)
        {
            // 分片文件列表，根据文件索引进行排序（正序）
            var tempFiles = Directory.GetFiles(tempFileFolder).OrderBy(x => Convert.ToInt32(x.Split("_")[2].Replace(".temp", ""))).ThenBy(x => x);

            // 判断文件数目是否一致
            if (Parameter.ChunkCount == tempFiles.Count())
            {
                var fileName = DateTime.Now.ToString("yyyyMMddHHmmssffff");

                // 文件保存路径
                var localFilePath = Path.Combine(FileBasePath, $"{fileName}.{Parameter.Ext}");

                var fs = new FileStream(localFilePath, FileMode.Create);

                // 循环分片文件进行合并
                foreach (var item in tempFiles)
                {
                    var itemBytes = File.ReadAllBytes(item);

                    fs.Write(itemBytes, 0, itemBytes.Length);

                    itemBytes = null;

                    File.Delete(item);
                }

                Directory.Delete(tempFileFolder);

                fs.Flush();
                fs.Close();
                fs.Dispose();

                var res = new ResponseMultipartUploadModel();
                res.LocalFilePath = localFilePath;
                res.FileName = fileName;
                res.Ext = Parameter.Ext;
                res.OriginalFileName = Parameter.Name;
                res.FileUrl = localFilePath.Replace(JsonConfig.JsonRead("MdSettings:MdFilePath"), JsonConfig.JsonRead("MdSettings:MdFileDomain"));

                Result.Data = res;
                Result.Msg = "merge success";
            }
            else
            {
                throw new AggregateException("文件合并失败");
            }
        }
        else
        {
            Result.Msg = "upload success";
        }
    }
}

